package bgg4j;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import core.Library;

import bgg4j.http.HttpClient;

public class Bgg {
    HttpClient http = null;
    private String baseURL = "http://www.boardgamegeek.com/";
    private String m_homedir = null;
    
    public final static String CHARSET = "UTF-8";
    //public final static String CHARSET = "ISO-8859-1";
    
    public Bgg() {
        http = new HttpClient();
    }

    public Bgg(String baseURL) {
        this();
        this.baseURL = baseURL;
    }

    public String getBaseURL(){
    	return baseURL;
    }
    
    public void setDir(String path){
    	m_homedir = path;
    }
    
    public final synchronized List<CollectedGame> loadSnapshotCollection(String userid) throws
    BggException {
    	DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
    	DocumentBuilder builder;
		try {
			String file = m_homedir + userid + "_collection_snapshot.xml";
			File snapshot = new File(file);
				if (snapshot.exists()){
				if (!snapshot.exists()){
					this.getSnapShotCollection(userid);
				}
				builder = dbfactory.newDocumentBuilder();
				Document doc = builder.parse(snapshot);
				return CollectedGame.constructCollectedGames(doc, this);
			}else{
				return new ArrayList<CollectedGame>(0);
			}
		} catch (Exception e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
			return new ArrayList<CollectedGame>(0);
		}
    }
    
    public final synchronized List<WishGame> loadSnapshotWishList(String userid) throws
    BggException {
    	DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
    	DocumentBuilder builder;
		try {
			File snapshot = new File(m_homedir + userid + "_wishlist_snapshot.xml");
			if (!snapshot.exists()){
				this.getSnapShotWishList(userid);
			}
			builder = dbfactory.newDocumentBuilder();
			Document doc = builder.parse(snapshot);
			return WishGame.constructWishGames(doc, this);
		} catch (Exception e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
			return new ArrayList<WishGame>(0);
		}
    }
    
    public final synchronized List<GameInfo> loadSnapshotCollectionGameInfo(String userid) throws
    BggException {
    	DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
    	DocumentBuilder builder;
		try {
			List<CollectedGame> list_collection = this.loadSnapshotCollection(userid);
			for (CollectedGame game : list_collection){
	        	String file = Library.HOMEDIR + "gamecache/" + String.valueOf(game.getGameID()) + "_gameinfo.xml";
	        	if ((!(new File(file).exists())))
	        		this.getSnapShotCollectionGameInfo(userid, Integer.toString(game.getGameID()));
			}

			builder = dbfactory.newDocumentBuilder();
			
			List<GameInfo> retlist = new ArrayList<GameInfo>(list_collection.size());
			
			for (CollectedGame game : list_collection){
	        	String file = Library.HOMEDIR + "gamecache/" + String.valueOf(game.getGameID()) + "_gameinfo.xml";
	        	if ((!(new File(file).exists())))
	        		this.getSnapShotCollectionGameInfo(userid, Integer.toString(game.getGameID()));
	        	
	        	Document doc = builder.parse(new File(file));
	        	retlist.add((GameInfo.constructGameInfo(doc, this)));
			}
			
			return retlist;
		} catch (Exception e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
			return new ArrayList<GameInfo>(0);
		}
    }
    
    public final synchronized List<GameInfo> loadSnapshotWishListGameInfo(String userid) throws
    BggException {
    	DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
    	DocumentBuilder builder;
    	
    		
			File snapshot = new File(m_homedir + userid + "_wishlist_gameinfo_snapshot.xml");
			if (!snapshot.exists()){
				List<WishGame> wishlist = this.loadSnapshotWishList(userid);
				for (WishGame game : wishlist){
					String file = Library.HOMEDIR + "gamecache/" + String.valueOf(game.getGameID()) + "_gameinfo.xml";
					if ((!(new File(file).exists())))
						try {
							this.getSnapShotWishListGameInfo(userid, Integer.toString(game.getGameID()));
						} catch (IOException e) {
							// TODO 自動生成された catch ブロック
							e.printStackTrace();
						}
				}
				List<GameInfo> retlist = new ArrayList<GameInfo>(wishlist.size());
				try {
					builder = dbfactory.newDocumentBuilder();
					
					for (WishGame game : wishlist){
						String file = Library.HOMEDIR + "gamecache/" + String.valueOf(game.getGameID()) + "_gameinfo.xml";
						if ((!(new File(file).exists())))
							this.getSnapShotCollectionGameInfo(userid, Integer.toString(game.getGameID()));
						Document doc = builder.parse(new File(file));
						retlist.add(GameInfo.constructGameInfo(doc,this));						
					}
					
				} catch (ParserConfigurationException e) {
					// TODO 自動生成された catch ブロック
					e.printStackTrace();
				} catch (IOException e) {
					// TODO 自動生成された catch ブロック
					e.printStackTrace();
				} catch (SAXException e) {
					// TODO 自動生成された catch ブロック
					e.printStackTrace();
				}
				return retlist;
			}
			return new ArrayList<GameInfo>(0);
    }
    
    public final synchronized void getFile(String url, String filepath) throws
    BggException, IOException {
    	if (url != null){
    		http.getFile(url, filepath);
    	}
    }
    
    public final synchronized List<QueryResult> getQueryResult(String key, boolean isExact) throws
    BggException{
    	String option = null;
    	if (isExact){
    		option = "&exact=1";
    	}else{
    		option = "";
    	}
    	return QueryResult.constructQueryResult(http.get(baseURL +
    									"xmlapi/search?search=" + key + option).asDocument(), this);
    }
    
    private final synchronized void getSnapShot(String userid, String filetype) throws
    BggException, IOException {
    	String url;
    	if (filetype.equals("wishlist")){
    		url = baseURL + "xmlapi/collection/" + userid + "?wishlist=1&own=0";
    	}else{
    		url = baseURL + "xmlapi/collection/" + userid + "?wishlist=0&own=1";
    	}
    	InputStreamReader in = http.get(url).asReader();
    	File file = new File(m_homedir +userid + "_"+ filetype +"_snapshot.xml");
    	FileOutputStream fos = new FileOutputStream(file);
        int ch;
        boolean isFirstChar = true;
        while ((ch = in.read()) != -1) {
        	if (isFirstChar == true && ch == '\n'){
        		isFirstChar = false;
        	}else{
        		fos.write(ch);
        		isFirstChar = false;
        	}
        }
       
        in.close();
        fos.flush();
        fos.close();
    }
    
    public final synchronized void getSnapShotCollection(String userid) throws
    BggException, IOException {
    	getSnapShot(userid, "collection");
    }
    
    public final synchronized void getSnapShotWishList(String userid) throws
    BggException, IOException {
    	getSnapShot(userid, "wishlist");
    }
    
    private final synchronized void getSnapShotGameInfo(String userid, String gameID, String listtype) throws
    BggException, IOException {
    	if (gameID.trim().length() > 0){
	    	InputStreamReader in = http.get(baseURL + "xmlapi/boardgame/" + gameID).asReader();
	    	String filename;
	    	filename = m_homedir + "/gamecache/" + gameID + "_gameinfo.xml";

	    	File file = new File(filename);
	    	FileOutputStream fos = new FileOutputStream(file);
	        int ch;
	        while ((ch = in.read()) != -1) {
	        	fos.write(ch);
	        }
	        in.close();
	        fos.flush();
	        fos.close();
    	}
    }
    
    public final synchronized void getSnapShotCollectionGameInfo(String userid, String gameID) throws
    BggException, IOException {
    	getSnapShotGameInfo(userid, gameID, "collection");
    }
    
    public final synchronized void getSnapShotWishListGameInfo(String userid, String gameID) throws
    BggException, IOException {
    	getSnapShotGameInfo(userid, gameID, "wishlist");
    }

}
